package root;

import java.awt.Color;
import java.awt.Graphics;

public class Koordinatensystem {
    // Interface für Mathematische Funktionen

    /*public interface Function {

        double f(double x);     // Liefert den y-Wert, wenn Eingabe = x-Wert
    }*/
    private static Graphics g;             // Grafikkontext
    private static int width;      // Breite und Höhe des "grafischen Bereiches"
    private static int height;
    private static double xStep;    // x-, y-Schritte
    private static double yStep;
    private static int xSpacing; // x-, y-Pixelabstand
    private static int ySpacing;

    /**
     * Konstruktor.
     * Initialisiert Member.
     * <p/>
     * @param g Grafikkontext
     * @param width Breite
     * @param height Höhe
     */
    public Koordinatensystem(Graphics g, int width, int height){
        Koordinatensystem.g = g;
        Koordinatensystem.width = width;
        Koordinatensystem.height = height;
    }

    /**
     * Konstruktor.
     * Initialisiert Member und setzt den Ursprung.
     * <p/>
     * @param g Grafikkontext
     * @param originX x-Koordinate des Ursprungs
     * @param originY y-Koordinate des Ursprungs
     * @param width Breite
     * @param height Höhe
     */
    public Koordinatensystem(Graphics g, int originX, int originY, int width, int height){
        this(g, width, height);
        setOrigin(originX, originY);
    }

    /**
     * Kosntruktor.
     * Initialisiert Member, setzt den Ursprung, die Intervalle und die Abstände
     * <p/>
     * @param g Grafikkontext
     * @param originX x-Koordinate des Ursprungs
     * @param originY y-Koordinate des Ursprungs
     * @param width Breite
     * @param height Höhe
     * @param xStep Schritte (x-Achse)
     * @param yStep Schritte (y-Achse)
     * @param xSpacing (grafischer) Abstand der x-Werte
     * @param ySpacing (grafischer) Abstand der y-Werte
     */
    public Koordinatensystem(Graphics g, int originX, int originY, int width, int height,
                             double xStep, double yStep, int xSpacing, int ySpacing){
        this(g, originX, originY, width, height);
        setSteps(xStep, yStep);
        setSpacing(xSpacing, ySpacing);
    }

    /**
     * Zeichnet eine Funktion
     * <p/>
     * @param function Funktion
     */
   /* public void drawFunction(Koordinatensystem.Function function){
        for (int i = -width / 2; i <= width / 2; i++){
            double fx = (double) i / xSpacing * xStep;
            double fy = function.f(fx);
            int y = (int) (fy * ySpacing / yStep);
            int i2 = i + 1;
            double fx2 = (double) i2 / xSpacing * xStep;
            double fy2 = function.f(fx2);
            int y2 = (int) (fy2 * ySpacing / yStep);
            g.drawLine(i, -y, i2, -y2);
        }
    }*/

    /**
     * Zeichnet eine Funktion in einer beliebigen Farbe
     * <p/>
     * @param function Funktion
     * @param color Farbe
     */
    /*public void drawFunction(Koordinatensystem.Function function, Color color){
        g.setColor(color);
        drawFunction(function);
        g.setColor(Color.black);
    }*/

    /**
     * Zeichnet das Raster
     */
    public void drawRaster(){
        g.setColor(Color.gray);
        // 1.Quadrant
        for (int x = xSpacing; x <= width; x += xSpacing){
            for (int y = -ySpacing; y >= -height; y -= ySpacing){
                g.drawRect(x, y, 1, 1);
            }
        }
        // 2.Quadrant
        /*for (int x = -xSpacing; x >= -width; x -= xSpacing){
            for (int y = -ySpacing; y >= -height; y -= ySpacing){
                g.drawRect(x, y, 1, 1);
            }
        }
        // 3.Quadrant
        for (int x = -xSpacing; x >= -width; x -= xSpacing){
            for (int y = ySpacing; y <= height; y += ySpacing){
                g.drawRect(x, y, 1, 1);
            }
        }
        // 4.Quadrant
        for (int x = xSpacing; x <= width; x += xSpacing){
            for (int y = ySpacing; y <= height; y += ySpacing){
                g.drawRect(x, y, 1, 1);
            }
        }*/
        g.setColor(Color.black);
    }

    /**
     * Zeichnet beide Achsen
     * <p/>
     * @param label Wenn true, bekommen die einzelnen Schritte Ziffern zugewiesen
     */
    public void drawAxes(boolean label){
        drawXAxis(label);
        drawYAxis(label);
    }

    /**
     * Zeichnet die X-Achse
     * <p/>
     * @param label Wenn true, bekommen die einzelnen Schritte Ziffern zugewiesen
     */
    public void drawXAxis(boolean label){
        g.setColor(Color.gray);
        double xSt /*
                 * = -xStep
                 */;
        g.drawLine(0, 0, width, 0);
        //g.drawLine(width - 30, -5, width - 20, 0);
        //g.drawLine(width - 30, 5, width - 20, 0);
        /*
         * for(int i = 0; i >= -width /2; i -= xSpacing) {
         * g.drawLine(i, -5, i, 5);
         * if(label && i != 0) {
         * int strW = g.getFontMetrics(g.getFont()).stringWidth(String.valueOf(i));
         * int strH = g.getFontMetrics(g.getFont()).getHeight();
         * g.drawString(String.valueOf(xSt), i - strW / 2, 5 + strH);
         * xSt += -xStep;
         * }
         * }
         */
        xSt = xStep;
        for (int i = 0; i <= width; i += xSpacing){
            g.drawLine(i, 0, i, 5);
            if (label && i != 0){
                int strW = g.getFontMetrics(g.getFont()).stringWidth(String.valueOf(i));
                int strH = g.getFontMetrics(g.getFont()).getHeight();
                g.drawString(String.valueOf(xSt), i - strW / 2, 5 + strH);
                xSt += xStep;
            }
        }
    }

    /**
     * Zeichnet die Y-Achse
     * <p/>
     * @param label Wenn true, bekommen die einzelnen Schritte Ziffern zugewiesen
     */
    public void drawYAxis(boolean label){
        g.setColor(Color.gray);
        double ySt = yStep;
        g.drawLine(0, -height, 0, height);
        //g.drawLine(-5, -height + 20, 0, -height + 10);
        //g.drawLine(5, -height + 20, 0, -height + 10);
        for (int i = 0; i >= -height; i -= ySpacing){
            g.drawLine(-5, i, 0, i);
            if (label && i != 0){
                int strH = g.getFontMetrics(g.getFont()).getHeight();
                g.drawString(String.valueOf(ySt), 10, i + strH / 4);
                ySt += yStep;
            }
        }
        /*
         * ySt = -yStep;
         * for(int i = 0; i <= height / 2; i += ySpacing) {
         * g.drawLine(-5, i, 5, i);
         * if(label && i != 0) {
         * int strH = g.getFontMetrics(g.getFont()).getHeight();
         * g.drawString(String.valueOf(ySt), 10, i + strH / 4);
         * ySt += -yStep;
         * }
         * }
         */
    }

    /**
     * Setzt die "Schritte"
     * <p/>
     * @param x Schritte auf der x-Achse
     * @param y Schritte auf der y-Achse
     */
    private void setSteps(double x, double y){
        Koordinatensystem.xStep = x;
        Koordinatensystem.yStep = y;
    }

    /**
     * Setzt die (grafischen) Abstände
     * <p/>
     * @param x Abstand auf der x-Achse
     * @param y Abstand auf der y-Achse
     */
    private void setSpacing(int x, int y){
        Koordinatensystem.xSpacing = x;
        Koordinatensystem.ySpacing = y;
    }

    /**
     * Setzt den Ursprung
     * <p/>
     * @param x x-Koordinate
     * @param y y-Koordinate
     */
    private void setOrigin(int x, int y){
        g.translate(x, y);
    }
}